Skip to content

[Ramses] Add analytical gravity#1673

Draft
nbrucy wants to merge 6 commits into
Shamrock-code:mainfrom
nbrucy:Analytical_gravity
Draft

[Ramses] Add analytical gravity#1673
nbrucy wants to merge 6 commits into
Shamrock-code:mainfrom
nbrucy:Analytical_gravity

Conversation

@nbrucy

@nbrucy nbrucy commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks @nbrucy for opening this PR!

You can do multiple things directly here:
1 - Comment pre-commit.ci run to run pre-commit checks.
2 - Comment pre-commit.ci autofix to apply fixes.
3 - Add label autofix.ci to fix authorship & pre-commit for every commit made.
4 - Add label light-ci to only trigger a reduced & faster version of the CI (need the full one before merge).
5 - Add label trigger-ci to create an empty commit to trigger the CI.

Once the workflow completes a message will appear displaying informations related to the run.

Also the PR gets automatically reviewed by gemini, you can:
1 - Comment /gemini review to trigger a review
2 - Comment /gemini summary for a summary
3 - Tag it using @gemini-code-assist either in the PR or in review comments on files

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @nbrucy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces the capability to simulate analytical gravity within the Ramses model. This feature allows for the inclusion of predefined gravitational potentials, such as a point mass, directly into the hydrodynamic simulations. It provides a flexible way to model systems where the gravitational field is known analytically, simplifying setup for specific astrophysical problems like accretion disks, without requiring a full N-body or Poisson solver. The changes span from core C++ solver logic to a new Python example, ensuring both functionality and demonstrability.

Highlights

  • Analytical Gravity Module: Introduced a new C++ module, ComputeAnalyticalGravity, responsible for calculating gravitational acceleration based on analytical formulas, starting with a point mass model.
  • Configuration for Analytical Gravity: Added a dedicated AnalyticalGravityConfig structure within SolverConfig.hpp to manage parameters for analytical gravity, such as point mass properties and softening length, and defined a new AnalyticalGravityMode enum.
  • Integration into Solver Graph: Integrated the NodeComputeAnalyticalGravity into the solver's computational graph, ensuring that gravitational forces are computed and applied to the fluid equations during the time integration step.
  • New Example Script: Added a new Python example script, godunov_disc.py, which demonstrates the use of analytical gravity for simulating a rotating disk, including initial conditions and plotting functionalities.
  • Momentum and Energy Update: Modified the TimeIntegrator to incorporate the calculated analytical gravitational forces, updating the momentum (rhov) and total energy (rhoe) fields accordingly.
Changelog
  • exemples/ramses/godunov_disc.py
    • Added a new Python script to set up and run a simulation of a rotating disk with analytical gravity.
    • Implemented functions for initial density, velocity, and energy mapping based on a softened point mass potential.
    • Included utilities for creating Cartesian coordinates and plotting density slices.
  • src/shammodels/ramses/CMakeLists.txt
    • Added src/modules/ComputeAnalyticalGravity.cpp to the list of source files for compilation.
  • src/shammodels/ramses/include/shammodels/ramses/SolverConfig.hpp
    • Removed the analytical_gravity boolean flag from GravityConfig.
    • Introduced AnalyticalGravityConfig struct to hold analytical gravity mode, point mass parameters (GM, position), and softening length.
    • Added analytical_gravity_config member to SolverConfig.
    • Updated is_coordinate_field_required() and added is_analytical_gravity_on() methods to reflect the new configuration structure.
  • src/shammodels/ramses/include/shammodels/ramses/config/enum_GravityMode.hpp
    • Defined a new enum AnalyticalGravityMode with NoAnalyticalGravity and POINTMASS options.
    • Added JSON serialization for AnalyticalGravityMode.
  • src/shammodels/ramses/include/shammodels/ramses/modules/ComputeAnalyticalGravity.hpp
    • Added a new header file defining the NodeComputeAnalyticalGravity class.
    • This class is an INode in the solver graph, designed to compute gravitational forces analytically.
  • src/shammodels/ramses/include/shammodels/ramses/modules/SolverStorage.hpp
    • Added a gravitational_force shared pointer to a Field<Tvec> to store the computed gravitational acceleration.
  • src/shammodels/ramses/src/Solver.cpp
    • Included the new ComputeAnalyticalGravity.hpp header.
    • Conditionally initialized the gravitational_force field in init_solver_graph() if analytical gravity is enabled.
    • Added NodeComputeAnalyticalGravity to the solver sequence, connecting its inputs (block counts, coordinates) and output (gravitational force).
  • src/shammodels/ramses/src/modules/ComputeAnalyticalGravity.cpp
    • Implemented the _impl_evaluate_internal() method for NodeComputeAnalyticalGravity.
    • Provided logic for computing gravitational acceleration for a POINTMASS using a softened potential.
    • Instantiated the template for f64_3 vector type.
  • src/shammodels/ramses/src/modules/TimeIntegrator.cpp
    • Modified forward_euler to load the gravitational_force field.
    • Added a conditional block to apply analytical gravity: it updates momentum (rhov) and total energy (rhoe) based on the gravitational force and timestep.
    • Ensured gravitational_force_patch completes its event state.
Activity
  • No activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces analytical gravity to the Ramses model, specifically a point mass analytical gravity. This involves adding new configuration structures, updating the solver graph to include a ComputeAnalyticalGravity node, and integrating the gravitational force into the time integration step. The changes also include a Python example demonstrating the usage of this new feature. The code appears to be well-structured and follows the existing patterns within the shamrock framework.

Comment thread exemples/ramses/godunov_disc.py Outdated
Comment on lines +48 to +50
if cs_expo == 0.5:
omega = point_mass_Gmass / (rc_soft * rc_soft * rs_soft)
omega -= (4.0 - cs_expo) * (cs * cs / rc_soft * rc_soft)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The calculation for omega when cs_expo == 0.5 seems to have a potential issue with rc_soft * rc_soft appearing twice in the denominator and numerator, respectively. This could lead to incorrect physical results. It looks like a typo where rc_soft * rc_soft might have been intended as rc_soft**2 or rc_soft in the denominator, and rc_soft**2 in the numerator. Please verify the physical formula for this specific case.

        omega = point_mass_Gmass / (rc_soft**2 * rs_soft)
        omega -= (4.0 - cs_expo) * (cs**2 / rc_soft**2)
        omega = max(omega, 0)

Comment thread exemples/ramses/godunov_disc.py Outdated
Comment on lines +88 to +90
rs_soft = np.sqrt(x**2 + y**2 + z**2 + gravity_softening**2)
x_soft = x * (rs_soft / rs)
y_soft = y * (rs_soft / rs)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The calculation of x_soft and y_soft involves rs_soft / rs. If rs is zero (e.g., at the exact center of the coordinate system), this will result in a division by zero error. While gravity_softening is used to prevent rs_soft from being zero, rs itself can still be zero. Consider adding a small epsilon to rs or handling this edge case explicitly to prevent potential runtime errors.

    rs = np.sqrt(x**2 + y**2 + z**2)
    rs_soft = np.sqrt(x**2 + y**2 + z**2 + gravity_softening**2)
    # Add a small epsilon to rs to prevent division by zero
    rs_safe = rs + 1e-10  # or a more appropriate small value
    x_soft = x * (rs_soft / rs_safe)
    y_soft = y * (rs_soft / rs_safe)

Comment on lines +80 to +83
for (u32 d = 0; d < shambase::VectorProperties<Tvec>::dimension; d++) {
ekin_old += rhov_old[d] * rhov_old[d];
}
ekin_old *= 0.5 / rho[id_a];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The calculation of ekin_old and ekin_new involves division by rho[id_a]. If rho[id_a] can be zero or very close to zero, this could lead to division by zero errors or numerical instability. Consider adding a check for rho[id_a] being non-zero or adding a small epsilon to the denominator to prevent such issues.

                            Tscal rho_safe = rho[id_a] + 1e-10; // Add a small epsilon
                            ekin_old *= 0.5 / rho_safe;

Comment on lines +91 to +94
for (u32 d = 0; d < shambase::VectorProperties<Tvec>::dimension; d++) {
ekin_new += rhov[id_a][d] * rhov[id_a][d];
}
ekin_new *= 0.5 / rho[id_a];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the previous comment, the calculation of ekin_new involves division by rho[id_a]. This also needs a check for zero or near-zero values of rho[id_a] to ensure numerical stability and prevent division by zero errors.

                            Tscal rho_safe = rho[id_a] + 1e-10; // Add a small epsilon
                            ekin_new *= 0.5 / rho_safe;

Comment thread exemples/ramses/godunov_disc.py Outdated

scale_fact = 1 / (cell_size * base)
cfg.set_scale_factor(scale_fact)
cfg.set_eos_gamma(1.4) # Can we have something which is NOT an EOS?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment Can we have something which is NOT an EOS? suggests uncertainty about the eos_gamma setting. If this parameter is not always related to an Equation of State, it might be beneficial to rename it or add a more descriptive comment explaining its broader applicability within the shamrock framework.

Comment thread exemples/ramses/godunov_disc.py Outdated
Comment on lines +195 to +196
(0, 0, 0), (cell_size, cell_size, cell_size), (base, base, base)
) # What is this doing?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment What is this doing? indicates a lack of clarity regarding the make_base_grid function. It would be helpful to add a more detailed explanation of its purpose and parameters, especially for future maintainers or users of this example script.

using Tscal = shambase::VecComponent<Tvec>;
GravityMode gravity_mode = NoGravity;
bool analytical_gravity = false; // whether to use an external analytical gravity
Tscal tol = 1e-6;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The analytical_gravity boolean was removed from GravityConfig but its comment // whether to use an external analytical gravity was also removed. It would be good to ensure that the purpose of GravityConfig and AnalyticalGravityConfig are clearly delineated, and that no important contextual information is lost.

for (u32 d = 0; d < dim; d++) {
r_squared += r_vec[d] * r_vec[d];
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The pow function in C++ operates on double by default. Using -1.5f suggests a float literal, which might lead to an implicit conversion and potential precision loss if Tscal is f64. It's generally safer to use pow(base, exponent) where base and exponent have the same type as Tscal to avoid unexpected behavior or to explicitly cast the exponent to Tscal.

                    Tscal one_over_r_cube_soft = pow(r_squared + config.epsilon_softening, static_cast<Tscal>(-1.5));

@tdavidcl

Copy link
Copy Markdown
Member

Wonderfull !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you

git mv exemples/ramses/godunov_disc.py examples/ramses/run_godunov_disc.py

to account for the new structure of the folder + enable the test to be run by the CI for the doc

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but for now it's still in debug mode :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i mean it's not like there is a choice since the original folder is gone on the main branch 😅
If you don't want to run the script yet just to the same command but do not rename the file.

};

template<class Tvec>
struct AnalyticalGravityConfig {

@tdavidcl tdavidcl Feb 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the structure of the config I would opt for something closer to the one in SPH
Or just use src/shammodels/common/include/shammodels/common/ExtForceConfig.hpp directly.

But this can be done for a latter PR. As you prefer


AnalyticalGravityMode analytical_gravity_mode = POINTMASS;
// parameters for analytical gravity can be added here
Tscal point_mass_GM = 1;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since G is set by the unit system i would just provide the mass directly

Comment on lines +64 to +65
Tscal one_over_r_cube_soft = pow(
r_squared + config.epsilon_softening * config.epsilon_softening, -1.5f);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Tscal one_over_r_cube_soft = pow(
r_squared + config.epsilon_softening * config.epsilon_softening, -1.5f);
Tscal one_over_r_cube_soft = sycl::pow(
r_squared + config.epsilon_softening * config.epsilon_softening, Tscal(1.5));

@github-actions

Copy link
Copy Markdown
Contributor

Workflow report

workflow report corresponding to commit 4910b0a
Commiter email is timothee.davidcleris@proton.me

Light CI is enabled. This will only run the basic tests and not the full tests.
Merging a PR require the job "on PR / all" to pass which is disabled in this case.

Pre-commit check report

Some failures were detected in base source checks checks.
Check the On PR / Linting / Base source checks (pull_request) job in the tests for more detailed output

❌ trailing-whitespace

Fixing src/shammodels/ramses/src/Solver.cpp

Suggested changes

Detailed changes :
diff --git a/src/shammodels/ramses/src/Solver.cpp b/src/shammodels/ramses/src/Solver.cpp
index dbd90f9c..4e79aed0 100644
--- a/src/shammodels/ramses/src/Solver.cpp
+++ b/src/shammodels/ramses/src/Solver.cpp
@@ -25,8 +25,8 @@
 #include "shammodels/ramses/SolverConfig.hpp"
 #include "shammodels/ramses/modules/AMRGridRefinementHandler.hpp"
 #include "shammodels/ramses/modules/BlockNeighToCellNeigh.hpp"
-#include "shammodels/ramses/modules/ComputeAnalyticalGravity.hpp"
 #include "shammodels/ramses/modules/ComputeAMRLevel.hpp"
+#include "shammodels/ramses/modules/ComputeAnalyticalGravity.hpp"
 #include "shammodels/ramses/modules/ComputeCFL.hpp"
 #include "shammodels/ramses/modules/ComputeCellAABB.hpp"
 #include "shammodels/ramses/modules/ComputeCoordinates.hpp"
@@ -989,9 +989,8 @@ void shammodels::basegodunov::Solver<Tvec, TgridVec>::init_solver_graph() {
         solver_sequence.push_back(
             std::make_shared<decltype(node_analytical_gravity)>(
                 std::move(node_analytical_gravity)));
-                
-                }
-                
+    }
+
     if (solver_config.amr_mode.need_amr_level_compute()) { // compute block amr level in patch
         modules::ComputeAMRLevel<TgridVec> node_amr_level{};
         node_amr_level.set_edges(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants